<template>
  <div class="flow-chart">
    <!-- <el-button @click="getChartData">getChartData</el-button> -->
    <div id="canvasPanel" ref="canvasPanel" @dragover.prevent />
    <el-drawer
      :with-header="false"
      :visible.sync="drawerVisible"
      show-close
      :wrapper-closable="drawerType === 'view' ? true : false"
      size="628px"
    >
      <div class="drawerForm">
        <div class="pageTitle">
          <div v-if="drawerType === 'edit'" class="titleText">{{ step === 1 ? '参数设置' : '被控芯片配置' }}</div>
        </div>
        <el-form
          ref="formData"
          :model="formData"
          :rules="rules"
          label-width="121px"
          label-suffix="："
          :label-position="drawerType === 'edit' ? 'top' : 'right'"
          style="margin: 20px 24px 10px; height: calc(100% - 137px)"
        >
          <el-form-item v-show="step === 1" prop="controlModeName">
            <template #label>
              <!-- 将原来的 <div> 内容移到 label 插槽中 -->
              <span style="white-space: nowrap">选择控制模式</span>
            </template>
            <div class="pageTitle" style="float: right">
              <i v-if="drawerType === 'view'" class="el-icon-edit-outline" @click="drawerType = 'edit'" />
            </div>
            <el-select
              v-if="drawerType === 'edit'"
              v-model="formData.controlModeName"
              @change="handleChangeControlModeId"
            >
              <el-option
                v-for="item in chipControlModeList"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              ></el-option>
            </el-select>
            <span v-else class="fontWeight">
              {{ chipControlModeList.find((item) => item.value === formData.controlModeName)?.label }}
            </span>
          </el-form-item>
          <template v-if="drawerType === 'edit'">
            <div v-show="step === 1" class="interfaceBox">
              <div class="title">所需接口列表</div>
              <div class="interfaceContent">
                <div
                  v-for="(item, index) in formData.interfaceList"
                  :key="item.slaveChipControlModeInterfaceId"
                  :class="{ selectedInterfaceInfo: isSelected(index), interfaceInfo: !isSelected(index) }"
                  :style="
                    isSelected(index + 1) ? 'border: 0px solid #1890ff;margin-bottom: 0px;padding-bottom:5px;' : ''
                  "
                >
                  <div class="item">
                    <el-tooltip
                      :disabled="getStrLength(item.slaveChipInterfaceName ?? '') < 15"
                      effect="dark"
                      :content="item.slaveChipInterfaceName"
                      placement="top"
                    >
                      <span class="interfaceName ellipsis">{{ item.slaveChipInterfaceName }}</span>
                    </el-tooltip>
                    <el-tooltip
                      :disabled="getStrLength(item.slaveChipInterfaceType ?? '') < 31"
                      effect="dark"
                      :content="item.slaveChipInterfaceType"
                      placement="top"
                    >
                      <span class="interfaceType ellipsis">
                        可配置接口类型：
                        {{ item.slaveChipInterfaceType }}
                      </span>
                    </el-tooltip>
                  </div>
                  <div class="descriptionContent">
                    <el-button
                      :style="{
                        backgroundColor: isConfigured(item) ? '#e8ebfa' : ''
                      }"
                      @click="handleClick('interfaceSetting', item, index)"
                    >
                      {{ isConfigured(item) ? '已配置' : '配置接口' }}
                    </el-button>
                    {{ item.slaveChipInterfaceDescription }}
                  </div>
                </div>
              </div>
            </div>
            <div v-if="step === 2" class="fromConf">
              <Parser
                v-if="formData?.formLayout"
                ref="parserForm"
                :init-data="formData.formLayoutFormData"
                :form-conf="formData.formLayout"
                :form-conf-style="{ height: 'calc(100vh - 300px)', overflow: 'auto' }"
              />
            </div>
          </template>
          <div v-else class="interfaceView">
            <div class="title">接口列表</div>
            <div class="interfaceContent">
              <div
                v-for="item in formData.interfaceList"
                :key="item.slaveChipControlModeInterfaceId"
                class="interfaceInfo"
              >
                <el-tooltip
                  :disabled="getStrLength(item.slaveChipInterfaceName ?? '') < 76"
                  effect="dark"
                  :content="item.slaveChipInterfaceName"
                  placement="top"
                >
                  <div class="interfaceName ellipsis">
                    {{ item.slaveChipInterfaceName }}
                  </div>
                </el-tooltip>
                <div class="content">
                  <div class="item">
                    <span>接口类型</span>
                    <span>{{ item.slaveChipInterfaceTypeName }}</span>
                  </div>
                  <div class="item">
                    <span>资源</span>
                    <span>{{ item.masterChipResourceName }}</span>
                  </div>

                  <div v-if="item.pinList.length > 0" class="item pin">引脚配置</div>
                  <div v-for="pin in item.pinList" :key="pin.projectSlaveChipConfigInterfacePinId">
                    <div class="item">
                      <span>{{ pin.masterChipPinName }}</span>
                      <span>{{ pin.masterChipPinCode }}</span>
                    </div>
                    <div v-for="parameter in pin.parameterList" :key="parameter.symbol" class="item">
                      <span>{{ parameter.symbol }}</span>
                      <span>{{ parameter.value }}</span>
                    </div>
                  </div>
                  <div v-if="item.parameterList.length > 0" class="item pin">参数配置</div>
                  <div v-for="pin in item.parameterList" :key="pin.parameterName">
                    <div class="item">
                      <span>{{ pin.parameterName }}</span>
                      <span>{{ pin.value }}</span>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </el-form>
        <div v-if="drawerType === 'edit'" class="drawerFooter" align="right">
          <el-popconfirm title="页面数据未保存，是否确认关闭？" @confirm="handleClick('close')">
            <el-button v-show="step === 1" slot="reference">关闭</el-button>
          </el-popconfirm>
          <el-button v-show="step === 2" @click="handleClick('before')">上一步</el-button>
          <template v-if="formData.formProperties.length > 0">
            <el-button v-show="step === 1" type="primary" @click="handleClick('next')">下一步</el-button>
            <el-button v-show="step === 2" type="primary" @click="handleClick('submit')">配置完成</el-button>
          </template>
          <el-button v-else type="primary" @click="handleClick('next')">配置完成</el-button>
        </div>
      </div>
    </el-drawer>
    <interfaceSetting
      ref="interfaceSetting"
      :master-chip-id="formData.masterChipId"
      :config_data="formData.interfaceList"
      :project_data="$attrs.project_data"
      :edge_id="currentEdge?._cfg?.id"
      @saveInterfaceSetting="saveInterfaceSetting"
    />
    <!-- config_data通过attrs传递芯片引脚配置参数 -->
    <el-dialog :title="'修改时钟配置'" :append-to-body="false" :visible.sync="dialogVisible" width="1164px">
      <clockSetting
        ref="clockSetting"
        :clock-pic="clockParameterFilesBase64"
        :disabled="false"
        :form-data="clockSettingformData"
        :form-fields="clockSettingFields"
        :form-rules="clockSettingRules"
        :chip-id="currentNode?._cfg?.model?.data?.chipId"
      />
      <div slot="footer" style="display: block; text-align: center">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleClick('clockSetting')">确认</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  getChipControlModeList,
  getChipControlModeInterfaceList,
  getChipDetail,
  adaptiveDriverLibrary
} from '@/api/project-management'
import { ruleCheck } from '@/api/rule-management'
import { getOneFormLayout } from '@/api/system-config'
import { getStrLength } from '@/utils/index'
import G6 from '@antv/g6'
import registerFactory from './graph/graph'
import Parser from '@/components/form-generator/components/parser/Parser'
import interfaceSetting from './interfaceSetting.vue'
import clockSetting from './clockSetting.vue'
import isEqual from 'lodash/isEqual'
import defaultSettings from '@/settings'
import { generateUUID, postMessage, receivedMessage } from '@/utils/index'
export default {
  name: 'IbsWebIndex',
  components: { Parser, interfaceSetting, clockSetting },
  props: {
    users: {
      type: Array,
      default: () => []
    }
  },
  emit: ['renderChart'],
  data() {
    return {
      drawerType: '',
      drawerVisible: false,
      chipControlModeList: [],
      formData: {},
      rules: {
        controlModeName: [{ required: true, message: '请选择控制模式', trigger: ['blur', 'change'] }]
      },
      dialogVisible: false,
      clockSettingformData: {},
      clockSettingFields: [],
      clockParameterFilesBase64: '',
      clockSettingRules: {},
      initClockSettingRules: {},
      step: 1,
      states: {
        2: {
          state: '已完成',
          bgColor: '#f6ffed',
          borderColor: '#52c41a',
          fontColor: '#52c41a'
        },
        1: {
          state: '执行中',
          bgColor: '#e6f7ff',
          borderColor: '#91d5ff',
          fontColor: '#1890ff'
        },
        0: {
          state: '未分配',
          bgColor: '#fffbe6',
          borderColor: '#ffe58f',
          fontColor: '#faad14'
        },
        4: {
          state: '延期',
          bgColor: '#fff2f0',
          borderColor: '#ffccc7',
          fontColor: '#ff4d4f'
        }
      },
      pageType: '',
      processId: null,
      processName: '',
      processRemark: '',
      // 连线图
      mode: 'drag-shadow-node',
      graph: undefined,
      configVisible: false,
      // 连线图弹窗
      isMouseDown: false,
      config: '',
      tooltip: '',
      top: 0,
      left: 0,
      // 数据列表
      nodeDataList: [],
      // 校验弹窗
      checkDialogVisible: false,
      checkDialogType: 'onlyCheck',
      errorList: [],
      warningList: [],
      currentNode: null,
      currentEdge: null,
      originalData: {},
      newAddNode: {},
      interfaceIndex: 0,
      selectorError: false,
      selectedIndices: [], // 存储选中的索引
      getChipControlModeListRequestId: generateUUID(),
      getChipControlModeInterfaceListRequestId: generateUUID(),
      changeControlModeIdRequestId: generateUUID(),
      adaptiveDriverLibraryRequestId: generateUUID(),
      getOneFormLayoutRequestId: generateUUID(),
      ruleCheckRequestId: generateUUID(),
      formDesignRuleCheckRequestId: generateUUID(),
      currentEdgeSetting: {},
      getChipDetailRequestId: generateUUID(),
      getChipDetailForClockSettingRequestId: generateUUID(),
      resetChipInfoID: generateUUID(),
      updateNodeDataRequestId: generateUUID()
    }
  },
  mounted() {
    receivedMessage(this.dataHandle)
  },
  methods: {
    dataHandle(result) {
      let self = this
      let e = defaultSettings.isWPF ? result : { data: JSON.parse(result) }
      if (e.data.webInfo.requestId === self.getChipControlModeListRequestId) {
        self.chipControlModeList = e.data.response.data
      } else if (e.data.webInfo.requestId === self.getChipControlModeInterfaceListRequestId) {
        self.setInterfaceList(e.data.response)
      } else if (e.data.webInfo.requestId === self.changeControlModeIdRequestId) {
        self.formData.interfaceList = e.data.response.data
      } else if (e.data.webInfo.requestId === self.adaptiveDriverLibraryRequestId) {
        self.getOneFormLayoutConfig(e.data.response)
      } else if (e.data.webInfo.requestId === self.getOneFormLayoutRequestId) {
        self.setEdgeFormLayout(e.data.response)
      } else if (e.data.webInfo.requestId === self.ruleCheckRequestId) {
        let res = e.data.response
        if (res.success) {
          const node = self.graph.getNodes().find(({ _cfg }) => _cfg.id === self.currentNode._cfg.id)
          const data = node._cfg.model.data
          self.resetChipInfo(data, res)
        } else {
          self.$message.error(res.message)
        }
      } else if (e.data.webInfo.requestId === self.formDesignRuleCheckRequestId) {
        let res = e.data.response
        if (res.success) {
          self.updateEdgeData(true, res)
        } else {
          self.$notify.error(res.message)
        }
      } else if (e.data.webInfo.requestId === self.getChipDetailRequestId) {
        self.beforeAddNode(e.data.response)
      } else if (e.data.webInfo.requestId === self.getChipDetailForClockSettingRequestId) {
        self.setClockSetting(e.data.response)
      } else if (e.data.webInfo.requestId.split(';')[0] === self.resetChipInfoID) {
        const responseData = e.data.response
        // const callbackArgs = e.data.webInfo.requestId.split(';')[1]
        // 字符串转换为JSON
        const callbackArgs = JSON.parse(e.data.webInfo.requestId.split(';')[1])
        const callbackFun = () => {
          self.handleRuleCheck(callbackArgs)
        }
        self.updateNodeData(responseData, callbackFun) // 在回调中直接调用?
        // })
        // })
      }
    },
    saved(data) {
      this.currentNode.item._cfg.model.data = data
      this.flowChartranslatetData = this.getChartData()
      this.initData(this.flowChartData)
      this.emitRenderChart()
    },
    emitRenderChart() {
      const chartData = this.getChartData()
      this.$emit('renderChart', chartData.content.nodes)
    },
    initData(res) {
      if (!this.graph) {
        // 创建画布
        this.createGraphic()
        this.initGraphEvent()
      }
      res.content.nodes.forEach((item) => {
        item.label = item.label.indexOf('\n') === -1 ? this.fittingString(item.data, 64, 14) : item.label
      })
      this.flowChartData = res
      this.processName = res.processName
      this.processRemark = res.remark
      this.graph?.read?.(res.content) // 读取数据
      this.graph?.translate(res.x, res.y)
      this.graph?.paint?.() // 渲染到页面
      this.setOriginalData()
      this.graph?.get?.('canvas').set('localRefresh', false) // 关闭局部渲染
    },
    setOriginalData() {
      this.originalData = this.getChartData()
    },
    handleChangeData(isChange) {
      if (isChange) {
        this.$emit('changeCurrentTag', false)
      } else {
        const newData = this.getChartData()
        if (!isEqual(this.originalData, newData)) {
          // console.log('数据已经发生改变')
          this.$emit('changeCurrentTag', false)
        }
        // else {
        //   console.log('数据没有发生改变')
        // }
      }
    },
    getChartData() {
      const obj = {
        nodes: [],
        edges: []
      }
      const nodes = this.graph.getNodes()
      const edges = this.graph.getEdges()
      nodes.forEach((item) => {
        const node = {
          id: item._cfg.model.id,
          label: item._cfg.model.label,
          content: item._cfg.model.content,
          anchorPoints: item._cfg.model.anchorPoints,
          data: item._cfg.model.data,
          x: item._cfg.model.x,
          y: item._cfg.model.y,
          style: {
            width: item._cfg.model.style.width
          }
        }
        obj.nodes.push(node)
      })
      edges.forEach((item) => {
        const edges = {
          id: item._cfg.model.id,
          source: item._cfg.model.source,
          target: item._cfg.model.target,
          sourceAnchor: item._cfg.model.sourceAnchor,
          targetAnchor: item._cfg.model.targetAnchor,
          masterChipNodeId: item._cfg.model.masterChipNodeId,
          slaveChipNodeId: item._cfg.model.slaveChipNodeId,
          style: item._cfg.model.style,
          data: item._cfg.model.data
        }
        obj.edges.push(edges)
      })
      // console.log(obj)
      let matrix = this.graph.cfg.group.attrs.matrix
      return {
        content: obj,
        x: matrix[6],
        y: matrix[7]
      }
    },
    saveData() {
      return new Promise((resolve, reject) => {
        const flowChartData = this.getChartData()
        if (flowChartData.content.nodes?.length) {
          resolve(flowChartData)
        } else {
          this.$message.error('请配置步骤')
          reject()
        }
      })
    },
    getTextWidth(text, font) {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      ctx.font = font
      return ctx.measureText(text).width
    },
    fittingString(data, maxWidth, fontSize) {
      var fontWidth = fontSize * 1.3 // 字号+边距
      maxWidth = maxWidth * 2 // 需要根据自己项目调整
      let str = data.displayName
      var width = getStrLength(str) * fontWidth
      var ellipsis = '…'
      var result = '\n'
      if (width > maxWidth) {
        var actualLen1 = Math.floor(maxWidth / fontWidth)
        var actualLen2 = Math.floor((maxWidth - 10) / fontWidth)
        if (width > maxWidth * 2) {
          result =
            result +
            str.substring(0, actualLen1) +
            '\n' +
            str.substring(actualLen1, actualLen1 + actualLen2) +
            ellipsis
        } else {
          result = result + str.substring(0, actualLen1) + '\n' + str.substring(actualLen1)
        }
        result = result + '\n\n'
      } else {
        result = '\n' + result + str + '\n\n'
      }
      let displayCategoryLen = getStrLength(data.displayCategory)
      if (displayCategoryLen < 15) {
        for (let i = 0; i < 15 - displayCategoryLen; i++) {
          result += '\r'
        }
      }
      result = result + data.displayCategory
      return result
    },
    beforeAddNode(res) {
      if (res.success) {
        let model = this.newAddNode
        model.data.pinFiles = res.data.pinFiles
        model.data.pinFilesBase64 = res.data.pinFilesBase64
        if (model.data.chipType === 1) {
          model.data.clockParameters = res.data.clockParameters
          model.data.clockParameterFiles = res.data.clockParameterFiles
          model.data.clockParameterFilesBase64 = res.data.clockParameterFilesBase64
          model.data.configData = {
            clockParameterFiles: res.data.clockParameterFiles,
            clockParameters: res.data.clockParameters.map((row) => {
              return { ...row, value: row.defaultValue ?? undefined }
            })
          }
        } else {
          model.data.performanceParameterFiles = res.data.performanceParameterFiles
          model.data.performanceParameterFilesBase64 = res.data.performanceParameterFilesBase64
        }
        this.graph.addItem('node', model)
        this.handleChangeData(true)
        this.emitRenderChart()
      } else {
        this.$message.error(res.message)
      }
    },
    // 添加节点
    addNode(transferData, { x, y }) {
      function getUuid() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
          var r = (Math.random() * 16) | 0
          var v = c === 'x' ? r : (r & 0x3) | 0x8
          return v.toString(16)
        })
      }
      const data = JSON.parse(transferData)
      const id = getUuid()
      data.componentId = id
      let anchorPoints = [
        [0, 0.5],
        [1, 0.5]
      ]
      if (data.chipType === 1) {
        const node = this.graph.getNodes().find(({ _cfg }) => _cfg.model.data.chipType === 1)
        if (node) {
          return this.$message('只能添加一个主控芯片')
        }
        data.masterChipId = data.chipId
      }

      this.newAddNode = {
        content: data.displayName,
        label: this.fittingString(data, 64, 14),
        id: id,
        type: 'image-node',
        dragEnable: true,
        anchorPoints: anchorPoints,
        data,
        style: {
          // width: this.getTextWidth(data.displayName) + 40
        },
        // 坐标
        x,
        y
      }
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.getChipDetailRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/chip/getChipInfo',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: { chipId: data.chipId },
          WebInfo: {
            requestId: this.getChipDetailRequestId
          }
        }
        postMessage(message)
      } else {
        getChipDetail({ chipId: data.chipId }).then((res) => {
          this.beforeAddNode(res)
        })
      }
    },

    // 连线前回调事件
    edgeAdd(source, target, sourceAnchor, targetAnchor) {
      if (
        source._cfg.model.data.chipType === 2 &&
        source._cfg.model.data.chipType === target._cfg.model.data.chipType
      ) {
        this.$message({
          message: '被控控件不能相连!',
          type: 'warning'
        })
        return
      }
      let result = true
      const edges = this.graph.getEdges()
      edges.every((edge) => {
        if (
          (edge.getSource().getID() === source.getID() && edge.getTarget().getID() === target.getID()) ||
          (edge.getSource().getID() === target.getID() && edge.getTarget().getID() === source.getID())
        ) {
          this.$message({
            message: '两个节点之间最多只有一条连线!',
            type: 'warning'
          })
          result = false
          return false
        }
        return true
      })
      if (!result) return
      let masterChipNodeId = null
      let masterChipId = null
      let slaveChipNodeId = null
      let slaveChipId = null
      if (source._cfg.model.data.chipType === 1) {
        masterChipNodeId = source.get('id')
        slaveChipNodeId = target.get('id')
        masterChipId = source._cfg.model.data.chipId
        slaveChipId = target._cfg.model.data.chipId
      } else {
        masterChipNodeId = target.get('id')
        slaveChipNodeId = source.get('id')
        masterChipId = target._cfg.model.data.chipId
        slaveChipId = source._cfg.model.data.chipId
      }
      this.currentEdgeSetting = {
        source,
        target,
        sourceAnchor,
        targetAnchor,
        masterChipNodeId,
        slaveChipNodeId,
        masterChipId,
        slaveChipId
      }
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.adaptiveDriverLibraryRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/driverLibrary/adaptiveDriverLibrary',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: { masterChipId, slaveChipId },
          WebInfo: {
            requestId: this.adaptiveDriverLibraryRequestId
          }
        }
        postMessage(message)
      } else {
        adaptiveDriverLibrary({ masterChipId, slaveChipId }).then((res) => {
          this.getOneFormLayoutConfig(res)
        })
      }
    },
    getOneFormLayoutConfig(res) {
      if (res.success) {
        this.currentEdgeSetting.driverLibraryId = res.data
        if (defaultSettings.isWPF || defaultSettings.isCEF) {
          this.getOneFormLayoutRequestId = generateUUID()
          let message = {
            RequestUrl: process.env.VUE_APP_URL + '/formLayout/getOneFormLayout',
            RequestMethod: 'POST',
            Headers: {
              contentType: 'application/json'
            },
            QueryParameter: {},
            RequestBody: {
              businessModule: 1,
              classificationId: res.data
            },
            WebInfo: {
              requestId: this.getOneFormLayoutRequestId
            }
          }
          postMessage(message)
        } else {
          getOneFormLayout({
            businessModule: 1,
            classificationId: res.data
          }).then((res) => {
            this.setEdgeFormLayout(res)
          })
        }
      } else {
        this.$message.error(res.message)
      }
    },
    setEdgeFormLayout(res) {
      const {
        source,
        target,
        sourceAnchor,
        targetAnchor,
        masterChipNodeId,
        slaveChipNodeId,
        masterChipId,
        slaveChipId,
        driverLibraryId
      } = this.currentEdgeSetting
      const id = `${+new Date() + (Math.random() * 10000).toFixed(0)}`
      this.graph.addItem('edge', {
        id, // edge id
        source: source.get('id'),
        target: target.get('id'),
        sourceAnchor,
        targetAnchor,
        masterChipNodeId,
        slaveChipNodeId,
        data: {
          configData: {
            interfaceList: [],
            controlModeName: '',
            formLayout: res.data,
            formProperties: this.getParserFormData(res.data?.fields ?? [])
          },
          masterChipId,
          slaveChipId,
          driverLibraryId
        },
        style: {
          lineDash: [5, 5]
        }
        // label:  'edge label',
      })
      const node = this.graph.getEdges().find(({ _cfg }) => _cfg.id === id)
      this.handleOpenParameterSetting(node)
      // console.log(node)
      this.handleChangeData(true)
    },
    getParserFormData(fields) {
      let result = []
      const trantToList = (fields) => {
        fields.forEach((item) => {
          if (item.__config__.children) {
            trantToList(item.__config__.children)
          } else {
            result.push({
              propertyName: item.__config__.label,
              propertyKey: item.__vModel__,
              propertyValue: item.__config__.defaultValue
            })
          }
        })
      }
      trantToList(fields)
      return result
    },
    // 点击节点事件
    nodeClick(e) {
      this.currentNode = e
      this.$refs.detailDrawer.showDrawer(e.item._cfg.model.data)
    },
    // 删除节点
    deleteNode(item) {
      // && item._cfg.edges.length > 0
      if (item._cfg.type === 'node') {
        this.$confirm('移除当前芯片将同步删除此芯片所有连线，是否确定移除?', '', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          showClose: false,
          center: true
        })
          .then(() => {
            this.handleChangeData(true)
            this.graph.removeItem(item)
            this.emitRenderChart()
          })
          .catch(() => {})
      } else {
        this.$confirm('是否确认删除此连线?', '', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          showClose: false,
          center: true
        })
          .then(() => {
            this.handleChangeData(true)
            this.graph.removeItem(item)
            this.emitRenderChart()
          })
          .catch(() => {})
      }
    },
    // 时钟设置
    clockSetting(item) {
      this.currentNode = item
      let data = item._cfg.model.data
      if (data.configData?.clockParameters && this.selectorError === false) {
        this.openClockSetting(data)
      } else {
        if (this.selectorError) {
          this.selectorError = !this.selectorError
        }
        if (defaultSettings.isWPF || defaultSettings.isCEF) {
          this.getChipDetailForClockSettingRequestId = generateUUID()
          let message = {
            RequestUrl: process.env.VUE_APP_URL + '/chip/getChipInfo',
            RequestMethod: 'POST',
            Headers: {
              contentType: 'application/json'
            },
            QueryParameter: {},
            RequestBody: { chipId: data.chipId },
            WebInfo: {
              requestId: this.getChipDetailForClockSettingRequestId
            }
          }
          postMessage(message)
        } else {
          getChipDetail({ chipId: data.chipId }).then((res) => {
            this.setClockSetting(res)
          })
        }
      }
    },
    setClockSetting(res) {
      if (res.success) {
        const node = this.graph.getNodes().find(({ _cfg }) => _cfg.id === this.currentNode._cfg.id)
        const data = node._cfg.model.data
        data.pinFiles = res.data.pinFiles
        data.pinFilesBase64 = res.data.pinFilesBase64
        if (data.chipType === 1) {
          data.clockParameters = res.data.clockParameters
          data.clockParameterFiles = res.data.clockParameterFiles
          data.clockParameterFilesBase64 = res.data.clockParameterFilesBase64
          data.configData = {
            clockParameterFiles: res.data.clockParameterFiles,
            clockParameters: res.data.clockParameters.map((row) => {
              return { ...row, value: row.defaultValue ?? undefined }
            })
          }
        } else {
          data.performanceParameterFiles = res.data.performanceParameterFiles
          data.performanceParameterFilesBase64 = res.data.performanceParameterFilesBase64
        }
        node.update({
          data
        })
        this.handleChangeData(true)
        this.emitRenderChart()
        this.openClockSetting(data)
      } else {
        this.$message.error(res.message)
      }
    },
    openClockSetting(data) {
      data.configData = {
        clockParameterFiles: data.clockParameterFiles,
        clockParameters: data.clockParameters.map((row) => {
          return { ...row, value: row.defaultValue ?? undefined }
        })
      }
      let clockSettingRules = {}
      this.dialogVisible = true
      this.clockParameterFilesBase64 = data.clockParameterFilesBase64
      this.clockSettingFields = data.configData.clockParameters
      let clockSettingformData = {}
      data.configData.clockParameters.forEach((row) => {
        clockSettingformData[row.symbol] = row.value
        if (row.dataType === 'enum' || row.validValues?.split(',')?.length > 1) {
          clockSettingRules[row.symbol] = [
            { required: true, message: '请选择' + row.parameterName, trigger: ['blur', 'change'] }
          ]
        } else if (['integer', 'float'].includes(row.dataType)) {
          clockSettingRules[row.symbol] = [
            { required: true, message: '请输入' + row.parameterName, trigger: 'blur' }
          ]
        }
      })
      this.clockSettingformData = clockSettingformData
      this.clockSettingRules = clockSettingRules
      this.initClockSettingRules = clockSettingRules
      this.$nextTick(() => {
        this.$refs.clockSetting.$refs.form.clearValidate()
        this.$refs.clockSetting.getRealFormFields()
      })
    },
    // 刷新连线图
    graphRender() {
      this.graph.render()
    },
    // 创建连线图
    createGraphic() {
      const vm = this
      const grid = new G6.Grid()
      const menu = new G6.Menu({
        offsetX: -20,
        offsetY: -50,
        itemTypes: ['node', 'edge'],
        getContent(e) {
          const outDiv = document.createElement('div')
          outDiv.style.width = '50px'
          outDiv.style.cursor = 'pointer'
          switch (e.item._cfg.type) {
            case 'node':
              if (e.item._cfg.model.data.chipType === 1) {
                outDiv.innerHTML =
                  '<div id="clockSetting">时钟配置</div><div style="margin-top:10px" id="deleteNode">移除芯片</div>'
              } else if (e.item._cfg.model.data.chipType === 2) {
                outDiv.innerHTML = '<div id="deleteNode">移除芯片</div>'
              }
              break
            case 'edge':
              outDiv.innerHTML = '<div id="deleteNode">删除连线</div>'
              break
          }

          return outDiv
        },
        handleMenuClick(target, item) {
          const { id } = target
          if (id) {
            vm[id](item)
          }
        }
      })
      let element = document.getElementById('canvasPanel')
      const cfg = registerFactory(G6, {
        width: element.offsetWidth,
        height: element.offsetHeight,
        // renderer: 'svg',
        layout: {
          type: '' // 位置将固定
        },
        // 所有节点默认配置
        defaultNode: {
          type: 'image-node',
          shape: 'image',
          img: require('@/assets/imgs/bigChip.png'), // 图片的URL
          style: {
            radius: 3,
            width: 144,
            height: 144,
            cursor: 'move',
            fill: 'transparent'
            // stroke: '#ffffff'
          },
          labelCfg: {
            style: {
              fontSize: 14,
              lineHeight: 16,
              cursor: 'move',
              fontWeight: 'bold',
              fill: '#E6EEFF'
            }
          }
        },
        // 所有边的默认配置
        defaultEdge: {
          type: 'polyline-edge', // 扩展了内置边, 有边的事件
          style: {
            radius: 2,
            offset: 15,
            stroke: '#54609f',
            lineWidth: 4,
            lineAppendWidth: 10, // 防止线太细没法点中
            endArrow: false
          }
        },
        // 覆盖全局样式
        nodeStateStyles: {
          'nodeState:default': {
            opacity: 1
          },
          'nodeState:hover': {
            opacity: 0.8
          },
          'nodeState:selected': {
            opacity: 0.9
          }
        },
        // 默认边不同状态下的样式集合
        edgeStateStyles: {
          'edgeState:default': {
            // lineDash: [4, 2],
            lineWidth: 4,
            stroke: '#54609f'
          },
          'edgeState:selected': {
            stroke: 'red',
            lineWidth: 4.5
          },
          'edgeState:hover': {
            animate: true,
            lineWidth: 4,
            animationType: 'dash'
            // stroke: '#54609f'
          }
        },
        modes: {
          // 支持的 behavior
          default: [
            'drag-canvas',
            // {
            //   type: 'drag-node',
            //   enableDelegate: true
            // },
            'drag-shadow-node',
            'canvas-event',
            'delete-item',
            'select-node',
            'hover-node',
            'active-edge',
            {
              type: 'tooltip',
              formatText: function formatText(model) {
                return model.content
              },
              shouldUpdate: function shouldUpdate(e) {
                return true
              }
            },
            {
              type: 'edge-tooltip',
              formatText: function formatText(model) {
                // console.log(model)
                if (
                  model.data.configData.controlModeName !== undefined &&
                  model.data.configData.controlModeName !== ''
                ) {
                  // console.log(model.data.configData.controlModeName)
                  return '点击连线查看芯片连接配置'
                }
                return '点击连线进入芯片连接配置'
              },
              shouldUpdate: function shouldUpdate(e) {
                return true
              }
            }
          ],
          originDrag: [
            'drag-canvas',
            'drag-node',
            'canvas-event',
            'delete-item',
            'select-node',
            'hover-node',
            'active-edge'
          ]
        },
        plugins: this.pageType === 'check' ? [grid] : [menu, grid]
        // ... 其他G6原生入参
      })
      this.graph = new G6.Graph(cfg)
      // console.log(cfg)
      this.graph.paint() // 渲染到页面
      this.graph.get('canvas').set('localRefresh', false) // 关闭局部渲染
      window.addEventListener('resize', () => {
        // 动态调整图表大小
        this.graph.changeSize(element.offsetWidth, element.offsetHeight)
      })
      // }
    },
    // 初始化图事件
    initGraphEvent() {
      this.graph.on('drop', (e) => {
        const { originalEvent } = e
        if (originalEvent.dataTransfer) {
          const transferData = originalEvent.dataTransfer.getData('dragComponent')
          if (transferData) {
            this.addNode(transferData, e)
          }
        }
      })

      this.graph.on('node:drop', (e) => {
        e.item.getEdges().forEach((edge) => {
          edge.clearStates(['edgeState:hover'])
        })
      })
      this.graph.on('canvas:click', (e) => {
        this.graph.getEdges().forEach((edge) => {
          edge.clearStates('edgeState')
        })
      })
      // let node
      // let dx
      // let dy
      // let isAnchorPoint = false
      // this.graph.on('node:dragstart', (e) => {
      //   const { item } = e
      //   const anchorPoints = e.item.getAnchorPoints()
      //   isAnchorPoint = false
      //   for (let i = 0; i < anchorPoints.length; i++) {
      //     const anchorPoint = anchorPoints[i]
      //     // 判断鼠标位置是否在锚点附近
      //     if (Math.abs(e.x - anchorPoint.x) < 10 && Math.abs(e.y - anchorPoint.y) < 10) {
      //       // 拖动的是锚点
      //       e.preventDefault()
      //       isAnchorPoint = true
      //       break
      //     }
      //   }
      //   if (isAnchorPoint) return
      //   const model = item.getModel()
      //   node = item
      //   dx = model.x - e.x
      //   dy = model.y - e.y
      // })

      // this.graph.on('node:drag', (e) => {
      //   !isAnchorPoint &&
      //     node &&
      //     this.graph.update(node, {
      //       x: e.x + dx,
      //       y: e.y + dy
      //     })
      // })
      // this.graph.on('node:dragend', (e) => {
      //   !isAnchorPoint &&
      //     node &&
      //     this.graph.updateItem(node, {
      //       x: e.x + dx,
      //       y: e.y + dy
      //     })
      //   node = undefined
      // })

      this.graph.on('node:click', (e) => {
        if (e && e.item) {
          // change
          // e.item.getEdges().forEach((edge) => {
          // edge.clearStates('edgeState')
          // edge.setState('edgeState', 'selected', true)
          // })
        }
        // this.nodeClick(e)
      })
      this.graph.on('after-node-selected', (e) => {
        this.configVisible = !!e
        if (e && e.item) {
          const model = e.item.get('model')

          this.config = model
          this.label = model.label
          this.labelCfg = {
            fontSize: model.labelCfg.fontSize,
            style: {
              fill: model.labelCfg.style.fill
            }
          }
          this.node = {
            fill: model.style.fill,
            borderColor: model.style.stroke,
            lineDash: model.style.lineDash || 'none',
            width: model.style.width,
            height: model.style.height,
            shape: model.type
          }
        }
      })
      // 鼠标拖拽到画布外时特殊处理
      this.graph.on('mousedown', (e) => {
        this.isMouseDown = true
      })
      this.graph.on('mouseup', (e) => {
        this.isMouseDown = false
      })
      this.graph.on('canvas:mouseleave', (e) => {
        this.graph.getNodes().forEach((x) => {
          const group = x.getContainer()
          group?.clearAnchor()
          x.clearStates('anchorActived')
        })
      })
      this.graph.on('on-node-mouseenter', (e) => {
        // if (e && e.item) {
        //   e.item.getOutEdges().forEach((edge) => {
        //     edge.clearStates('edgeState')
        //     edge.setState('edgeState', 'hover')
        //   })
        // }
      })
      this.graph.on('dragend', () => {
        this.handleChangeData()
      })
      this.graph.on('on-node-mousemove', (e) => {
        if (e && e.item) {
          // console.log('move')
          this.tooltip = e.item.get('model').id
          this.left = e.clientX
          this.top = e.clientY
        }
      })
      this.graph.on('on-node-mouseleave', (e) => {
        // if (e && e.item) {
        //   this.tooltip = ''
        //   if (e && e.item) {
        //     e.item.getOutEdges().forEach((edge) => {
        //       edge.clearStates('edgeState')
        //     })
        //   }
        // }
      })
      this.graph.on('before-node-removed', ({ target, callback }) => {
        setTimeout(() => {
          // 确认提示
          callback(true)
        }, 1000)
      })
      this.graph.on('after-node-dblclick', (e) => {
        if (e && e.item) {
          console.log(e.item)
        }
      })
      this.graph.on('after-edge-selected', (e) => {
        this.configVisible = !!e
        // console.log(e)
        if (e && e.item) {
          this.handleOpenParameterSetting(e.item)
        }
        // if (e && e.item) {
        //   this.config = e.item.get('model').id

        //   this.graph.updateItem(e.item, {
        //     // shape: 'line-edge',
        //     style: {
        //       radius: 10,
        //       lineWidth: 2
        //     }
        //   })
        // }
        // if (e && e.item) {
        // this.drawerVisible = true
        // console.log('edgeclick')
        // }
      })
      this.graph.on('on-edge-click', (e) => {
        console.log(e)
      })
      this.graph.on('after-edge-dblclick', (e) => {
        // if (e && e.item) {
        //   this.handleOpenParameterSetting(e.item)
        // }
      })
      // this.graph.on('on-edge-mousemove', (e) => {
      //   if (e && e.item) {
      //     this.tooltip = e.item.get('model').label
      //     this.left = e.clientX
      //     this.top = e.clientY
      //   }
      // })
      let hasState = false
      this.graph.on('on-edge-mouseleave', (e) => {
        if (e && e.item) {
          if (hasState) {
            this.graph.clearItemStates(e.item)
            e.item.setState('edgeState', 'selected')
          } else {
            this.graph.clearItemStates(e.item, 'edgeState')
          }
        }
      })
      this.graph.on('on-edge-mouseenter', (e) => {
        if (e && e.item) {
          hasState = e.item.hasState('edgeState:selected')
          // change
          // e.item.setState('edgeState', 'hover')
          // console.log(e.item.setState('edgeState', 'hover'), hasState)
        }
      })

      this.graph.on('before-edge-add', ({ source, target, sourceAnchor, targetAnchor }) => {
        this.edgeAdd(source, target, sourceAnchor, targetAnchor)
      })
    },
    getStrLength(str) {
      return getStrLength(str)
    },
    setInterfaceList(res) {
      let interfaceList = res.data
      let obj = {}
      interfaceList.forEach((row) => {
        obj[row.slaveChipControlModeInterfaceId] = row.interfaceTypeOptionList
      })
      this.$set(
        this.formData,
        'interfaceList',
        this.currentEdge._cfg.model.data.configData.interfaceList.map((row) => {
          return {
            ...row,
            interfaceTypeOptionList: obj[row.slaveChipControlModeInterfaceId] ?? []
          }
        })
      )
    },
    // 线条参数设置
    handleOpenParameterSetting(item) {
      let configData = item._cfg.model.data.configData
      const edge = this.graph.getEdges().find(({ _cfg }) => _cfg.id === item._cfg.id)
      if (configData?.formLayout?.fields && configData?.formProperties?.length === 0) {
        configData.formProperties = this.getParserFormData(configData.formLayout?.fields ?? [])
        edge.update({
          data: {
            ...item._cfg.model.data,
            configData
          }
        })
      } else {
        if (!configData.formProperties) {
          configData.formProperties = []
          edge.update({
            data: {
              ...item._cfg.model.data,
              configData
            }
          })
        }
      }
      this.step = 1
      this.currentEdge = item
      let source = item._cfg.source
      let target = item._cfg.target
      let formLayoutFormData = {}
      configData.formProperties.forEach((row) => {
        formLayoutFormData[row.propertyKey] = row.propertyValue
      })
      let formProperties = this.getParserFormData(item._cfg.model.data.configData.formLayout?.fields ?? [])
      let formPropertiesObj = {}
      formProperties.forEach((property) => {
        formPropertiesObj[property.propertyKey] = property.propertyName
      })
      this.formData = {
        driverLibraryId: item._cfg.model.data.driverLibraryId,
        projectSlaveChipConfigId: item._cfg.model.data.configData.projectSlaveChipConfigId,
        controlModeName: item._cfg.model.data.configData.controlModeName,
        interfaceList: item._cfg.model.data.configData.interfaceList,
        formLayout: item._cfg.model.data.configData.formLayout,
        formProperties: item._cfg.model.data.configData.formProperties.map((row) => {
          return { ...row, propertyName: formPropertiesObj[row.propertyKey] }
        }),
        formLayoutFormData: formLayoutFormData
      }
      if (source._cfg.model.data.chipType === 1) {
        this.formData.masterChipId = source._cfg.model.data.chipId
        this.formData.slaveChipId = target._cfg.model.data.chipId
        this.formData.slaveNodeId = target._cfg.id
      } else {
        this.formData.masterChipId = target._cfg.model.data.chipId
        this.formData.slaveChipId = source._cfg.model.data.chipId
        this.formData.slaveNodeId = source._cfg.id
      }
      if (this.formData.controlModeName) {
        let params = {
          driverLibraryId: this.formData.driverLibraryId,
          masterChipId: this.formData.masterChipId,
          chipControlModeName: this.formData.controlModeName
        }
        if (defaultSettings.isWPF || defaultSettings.isCEF) {
          this.getChipControlModeInterfaceListRequestId = generateUUID()
          let message = {
            RequestUrl: process.env.VUE_APP_URL + '/chipControlModeInterface/getList',
            RequestMethod: 'POST',
            Headers: {
              contentType: 'application/json'
            },
            QueryParameter: {},
            RequestBody: params,
            WebInfo: {
              requestId: this.getChipControlModeInterfaceListRequestId
            }
          }
          postMessage(message)
        } else {
          getChipControlModeInterfaceList(params).then((res) => {
            this.setInterfaceList(res)
          })
        }
      }

      this.chipControlModeList = []
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.getChipControlModeListRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/chipControlMode/getOptionList',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: { driverLibraryId: this.formData.driverLibraryId },
          WebInfo: {
            requestId: this.getChipControlModeListRequestId
          }
        }
        postMessage(message)
      } else {
        getChipControlModeList({
          driverLibraryId: this.formData.driverLibraryId
        }).then((res) => {
          this.chipControlModeList = res.data
        })
      }
      if (item._cfg.model.style.lineDash?.length > 0) {
        this.drawerType = 'edit'
      } else {
        this.drawerType = 'view'
      }
      this.drawerVisible = true
      this.$nextTick(() => {
        this.$refs.formData.clearValidate()
      })
    },
    // 选择控制模式改变
    handleChangeControlModeId(val) {
      if (val) {
        let params = {
          driverLibraryId: this.formData.driverLibraryId,
          masterChipId: this.formData.masterChipId,
          chipControlModeName: this.formData.controlModeName
        }
        if (defaultSettings.isWPF || defaultSettings.isCEF) {
          this.changeControlModeIdRequestId = generateUUID()
          let message = {
            RequestUrl: process.env.VUE_APP_URL + '/chipControlModeInterface/getList',
            RequestMethod: 'POST',
            Headers: {
              contentType: 'application/json'
            },
            QueryParameter: {},
            RequestBody: params,
            WebInfo: {
              requestId: this.changeControlModeIdRequestId
            }
          }
          postMessage(message)
        } else {
          getChipControlModeInterfaceList(params).then((res) => {
            this.formData.interfaceList = res.data
          })
        }
      } else {
        this.formData.interfaceList = []
      }
    },
    handleClick(name, row = {}, index = 0) {
      if (name === 'before') {
        this.step = 1
      } else if (name === 'close') {
        this.drawerVisible = false
        this.toggleInterfaceStyle()
      } else if (name === 'next') {
        this.toggleInterfaceStyle()
        this.$refs.formData.validate((valid) => {
          if (valid) {
            let result = true
            this.formData.interfaceList.every((item) => {
              if (!item.slaveChipInterfaceTypeName) {
                result = false
                this.$notify.warning(item.slaveChipInterfaceName + '配置接口没有设置')
                return false
              }
              return true
            })
            if (result) {
              if (this.formData.formProperties.length > 0) {
                this.step = 2
              } else {
                this.handleClick('submit')
              }
            }
          }
        })
      } else if (name === 'interfaceSetting') {
        this.toggleInterfaceStyle(index)
        this.interfaceIndex = index
        this.$refs.interfaceSetting.is(row)
      } else if (name === 'clockSetting') {
        this.clockSettingRules = this.initClockSettingRules
        const node = this.graph.getNodes().find(({ _cfg }) => _cfg.id === this.currentNode._cfg.id)
        const data = node._cfg.model.data
        let parameterData = {}
        this.$refs.clockSetting.realFormFields.forEach((item) => {
          if (item.show) {
            parameterData[item.symbol] = this.clockSettingformData[item.symbol]
          }
        })
        let params = {
          checkDataList: [
            {
              chipId: data.chipId,
              ruleSetType: 4,
              configDataList: [
                {
                  parameterData: parameterData
                }
              ]
            }
          ]
        }
        if (defaultSettings.isWPF || defaultSettings.isCEF) {
          this.ruleCheckRequestId = generateUUID()
          let message = {
            RequestUrl: process.env.VUE_APP_URL + '/project/ruleCheck',
            RequestMethod: 'POST',
            Headers: {
              contentType: 'application/json'
            },
            QueryParameter: {},
            RequestBody: params,
            WebInfo: {
              requestId: this.ruleCheckRequestId
            }
          }
          postMessage(message)
        } else {
          ruleCheck(params).then((res) => {
            const node = this.graph.getNodes().find(({ _cfg }) => _cfg.id === this.currentNode._cfg.id)
            const data = node._cfg.model.data
            const callback = () => {
              this.handleRuleCheck(res)
            }
            this.resetChipInfo(data, callback)
          })
        }
      } else {
        // submit
        const submitData = this.$refs.parserForm?.submitForm()
        if (this.formData.formProperties.length === 0 || submitData?.state) {
          if (this.formData.formProperties.length > 0) {
            let params = {
              checkDataList: [
                {
                  // chipId: data.chipId,
                  driverLibraryId: this.currentEdge._cfg.model.data.driverLibraryId,
                  ruleSetType: 7,
                  configDataList: [
                    {
                      parameterData: submitData.data
                    }
                  ]
                }
              ]
            }
            if (defaultSettings.isWPF || defaultSettings.isCEF) {
              this.formDesignRuleCheckRequestId = generateUUID()
              let message = {
                RequestUrl: process.env.VUE_APP_URL + '/project/ruleCheck',
                RequestMethod: 'POST',
                Headers: {
                  contentType: 'application/json'
                },
                QueryParameter: {},
                RequestBody: params,
                WebInfo: {
                  requestId: this.formDesignRuleCheckRequestId
                }
              }
              postMessage(message)
            } else {
              ruleCheck(params).then((res) => {
                this.updateEdgeData(true, res)
              })
            }
          } else {
            this.updateEdgeData(false)
          }
        }
      }
    },
    updateEdgeData(isFlag, res = {}) {
      if (isFlag) {
        if (res.success) {
          let notMatchConditionKeyList = res.data[0].configDataList[0].notMatchConditionKeyList
          // notMatchConditionKeyList = ['over_sampling', 'range', 'sample_rate']
          if (notMatchConditionKeyList.length > 0) {
            let propertyNames = this.formData.formProperties
              .filter((item) => {
                return notMatchConditionKeyList.includes(item.propertyKey)
              })
              .map((obj) => obj.propertyName)
            this.$notify.error({
              title: '错误',
              message: propertyNames.join(',') + '参数配置超出有效值范围',
              duration: 0
            })
            return
          }
        } else {
          this.$notify.error(res.message)
          return
        }
      }
      const submitData = this.$refs.parserForm?.submitForm()
      const edge = this.graph.getEdges().find(({ _cfg }) => _cfg.id === this.currentEdge._cfg.id)
      const data = edge._cfg.model.data
      edge.update({
        style: {
          lineDash: []
        },
        data: {
          ...data,
          configData: {
            ...this.formData,
            formProperties: this.formData.formProperties.map((row) => {
              return {
                propertyName: row.propertyName,
                propertyKey: row.propertyKey,
                propertyValue: submitData.data[row.propertyKey]
              }
            })
          }
        }
      })
      this.handleChangeData()
      this.drawerVisible = false
    },
    saveInterfaceSetting(data) {
      // console.log(data)
      this.$set(this.formData.interfaceList, this.interfaceIndex, data)
    },
    resetChipInfo(data, callback) {
      // 判断是web端还是客户端调用
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        // 客户端调用
        const callbackArgs = JSON.stringify(callback)
        const message = {
          RequestUrl: `${process.env.VUE_APP_URL}/chip/getChipInfo`,
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          RequestBody: { chipId: data.chipId },
          WebInfo: { requestId: this.resetChipInfoID + ';' + callbackArgs }
        }
        postMessage(message)
      } else {
        // web端调用
        getChipDetail({ chipId: data.chipId }).then((res) => {
          // 修改此处，将回调函数传递给updateNodeData
          this.updateNodeData(res, callback)
        })
      }
    },
    // 更新节点数据
    updateNodeData(res, callback) {
      if (res.success) {
        const node = this.graph.getNodes().find(({ _cfg }) => _cfg.id === this.currentNode._cfg.id)
        const data = node._cfg.model.data
        data.pinFiles = res.data.pinFiles
        data.pinFilesBase64 = res.data.pinFilesBase64
        if (data.chipType === 1) {
          data.clockParameters = res.data.clockParameters
          data.clockParameterFiles = res.data.clockParameterFiles
          data.clockParameterFilesBase64 = res.data.clockParameterFilesBase64
          data.configData = {
            clockParameterFiles: res.data.clockParameterFiles,
            clockParameters: res.data.clockParameters.map((row) => {
              return { ...row, value: row.defaultValue ?? undefined }
            })
          }
        } else {
          data.performanceParameterFiles = res.data.performanceParameterFiles
          data.performanceParameterFilesBase64 = res.data.performanceParameterFilesBase64
        }
        node.update({
          data
        })
        // clockSettingFields = data.configData.clockParameters
        this.$set(this, 'clockSettingFields', data.configData.clockParameters)
        callback()
      }
    },
    handleRuleCheck(res) {
      const setRules = (fields, rules, notMatchConditionKeyList) => {
        fields.forEach((item) => {
          if (notMatchConditionKeyList.includes(item.symbol)) {
            rules[item.symbol] || (rules[item.symbol] = [])
            rules[item.symbol].push({
              validator: (rule, value, callback) => {
                let validValues = item.validValues
                if (validValues && validValues.indexOf('~') !== -1) {
                  let arr = validValues.split('~')
                  let min = Number(arr[0])
                  let max = Number(arr[1])
                  if (value < min || value > max) {
                    callback(
                      new Error(
                        item.parameterName + '参数配置超出有效值范围,有效范围应在(' + min + '~' + max + ')之间'
                      )
                    )
                  } else {
                    callback()
                  }
                } else {
                  let validValueList = validValues.split(',')
                  const flag = validValueList.some((validValue) => validValue === value)
                  // 如果validValues中不包含value，则报错
                  if (validValues && !flag) {
                    callback(
                      new Error(
                        item.parameterName + '参数配置超出有效值范围,有效范围应在集合{' + validValues + '}内'
                      )
                    )
                    this.selectorError = true
                  } else {
                    callback()
                  }
                }
              },
              trigger: ['blur', 'change']
            })
          }
        })
      }
      setRules(
        this.clockSettingFields,
        this.clockSettingRules,
        res.data[0].configDataList[0].notMatchConditionKeyList
      )
      this.$nextTick(() => {
        this.$refs.clockSetting.$refs.form.validate((valid) => {
          if (valid) {
            const node = this.graph.getNodes().find(({ _cfg }) => _cfg.id === this.currentNode._cfg.id)
            const data = node._cfg.model.data
            let clockSettingFields = this.$refs.clockSetting.realFormFields.map((item) => {
              return {
                ...item,
                value: item.show ? this.clockSettingformData[item.symbol] : undefined
              }
            })

            node.update({
              data: {
                ...data,
                configData: {
                  clockParameterFiles: data.configData.clockParameterFiles,
                  clockParameters: clockSettingFields,
                  projectMasterChipConfigId: data.configData.projectMasterChipConfigId
                }
              }
            })
            this.handleChangeData()
            this.dialogVisible = false
          }
        })
      })
    },
    isConfigured(item) {
      return !!item.slaveChipInterfaceTypeName // 将非空值转换为布尔值
    },
    toggleInterfaceStyle(index) {
      // 变更选中状态
      // 清空所有的选中
      this.selectedIndices = []
      if (index != undefined) {
        // 添加选中
        this.selectedIndices.push(index)
      }
    },
    isSelected(index) {
      return this.selectedIndices.includes(index)
    }
  }
}
</script>

<style lang="less" scoped>
@import '~@/styles/graph.less';
#canvasPanel {
  width: 100%;
  height: 100%;
}
.fontWeight {
  font-weight: bold;
}
.flow-chart {
  width: 100%;
  height: 100%;
  position: relative;
}
.dataNull {
  color: #c4c0c0;
  padding-top: 7px;
  height: 44px;
}
.node {
  display: inline-block;
  margin-bottom: 10px;
  margin-right: 10px;
  cursor: move;
  padding: 8px;
  border: 1px solid #b9c9f1;
  border-radius: 4px;
  min-width: 100px;
  font-size: 14px;
  color: #b9c9f1;
  text-align: center;
  box-sizing: border-box;
  white-space: nowrap;
  -webkit-user-drag: element;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.drawerForm {
  display: flex;
  flex-direction: column;
  height: 100%;
  color: #303453;
  /deep/label {
    font-weight: 400;
    padding-bottom: 0;
  }
}
.drawerFooter {
  justify-content: right;
  padding: 20px;
}
.pageTitle {
  padding-top: 15px;
  padding-left: 24px;
  padding-right: 20px;
  font-size: 16px;
  display: flex;
  justify-content: space-between;

  .titleText {
    display: inline;
    padding-right: 20px;
    padding-left: 5px;
    font-weight: bold;
  }
  .el-icon-edit-outline {
    font-size: 20px;
    cursor: pointer;
  }
}
.interfaceBox {
  height: calc(100% - 20px);
  font-size: 14px;
  color: #303453;
  .title {
    font-weight: bold;
    margin-bottom: 12px;
  }
  .interfaceContent {
    height: calc(100% - 90px);
    overflow-y: auto;
    padding-right: 10px;
    width: 600px;
  }
  .interfaceInfo {
    margin-bottom: 20px;
    border-bottom: 1px dashed #cfd9e6;
    //内边距设置
    padding-right: 10px;
    padding-left: 10px;

    .item {
      padding-bottom: 20px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      .interfaceName {
        width: 220px;
        height: 30px;
        text-align: center;
        line-height: 30px;
        background: #e8ebfa;
        border-radius: 14px;
        padding: 0 10px;
        font-weight: bold;
      }
      .interfaceType {
        width: 350px;
        text-align: right;
      }
    }
    .descriptionContent {
      padding-bottom: 20px;
      // display: flex;
      // justify-content: space-between;
      word-break: break-all;
      line-height: 20px;
      .el-button {
        float: right;
        margin-left: 5px;
      }
    }
  }
  .selectedInterfaceInfo {
    margin-bottom: 20px; //两个接口之间的间距
    //内边距设置
    padding-right: 10px;
    padding-left: 10px;
    padding-top: 19px;
    // 虚线边框设置
    border-top: 1.2px solid rgba(167, 215, 255, 0.4); //被选中后的边框设置
    border-bottom: 1.2px solid rgba(167, 215, 255, 0.4); //被选中后的边框设置
    background-color: rgba(204, 232, 255, 0.2);

    .item {
      padding-bottom: 20px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      .interfaceName {
        width: 220px;
        height: 30px;
        text-align: center;
        line-height: 30px;
        background: #e8ebfa;
        border-radius: 14px;
        padding: 0 10px;
        font-weight: bold;
      }
      .interfaceType {
        width: 350px;
        text-align: right;
      }
    }
    .descriptionContent {
      padding-bottom: 20px;
      // display: flex;
      // justify-content: space-between;
      word-break: break-all;
      line-height: 20px;
      .el-button {
        float: right;
        margin-left: 5px;
      }
    }
  }
}
.interfaceView {
  height: 100%;
  border-top: 1px dashed #cfd9e6;
  padding-top: 18px;
  .title {
    font-weight: bold;
    margin-bottom: 16px;
  }
  .interfaceContent {
    height: calc(100% - 32px);
    overflow-y: auto;
    .interfaceName {
      width: 100%;
      font-weight: bold;
      margin-bottom: 10px;
    }
    .content {
      padding-bottom: 10px;
      .item {
        display: flex;
        align-items: center;
        border: 1px solid #efefef;

        > span {
          padding: 8px 12px;
          display: inline-block;
          word-wrap: break-word;
          white-space: pre-wrap;
          word-break: break-all;
        }
        > span:first-of-type {
          background-color: #fafafa;
          width: 120px;
          border-right: 1px solid #efefef;
          flex-shrink: 0;
        }
        > span:nth-child(2) {
          flex: 1;
        }
      }
      .item:not(:last-child) {
        border-bottom: none;
      }
      .pin {
        padding: 8px 12px;
      }
    }
  }
}
.fromConf {
  height: calc(100% - 32px);
  overflow-y: auto;
  overflow-x: hidden;
  /deep/.el-form--label-right .el-form-item {
    display: flex;
    .el-form-item__content {
      margin-left: 0 !important;
      width: 100%;
    }
  }
}
</style>
<style>
.g6-tooltip {
  border: 1px solid #e2e2e2;
  border-radius: 4px;
  font-size: 12px;
  color: #545454;
  background-color: rgba(255, 255, 255, 0.9);
  padding: 10px 8px;
  box-shadow: rgb(174, 174, 174) 0px 0px 10px;
}
</style>
